import wx
from socket import *
import threading
from concurrent.futures import ThreadPoolExecutor


class Server(wx.Frame):
    # 构造方法
    def __init__(self):
        # 实例属性
        # 服务器的启动状态
        self.isOn = False
        # 创建socket对象
        self.server_socket = socket()
        # 绑定ip地址和端口号
        self.server_socket.bind(('0.0.0.0', 9999))
        # 监听
        self.server_socket.listen(5)
        # 保存所有客户端（字典）
        self.client_thread_dict = {}
        # 创建线程池
        self.pool = ThreadPoolExecutor(max_workers=10)

        # 界面布局
        wx.Frame.__init__(self, None, title="多人聊天室", size=(450, 600), pos=(0, 50))

        # 创建面板
        self.pl = wx.Panel(self)
        # 创建按钮
        # 启动服务器
        self.start_btn = wx.Button(self.pl, label='启动服务器', size=(200, 40), pos=(10, 10))
        # 保存聊天记录
        self.save_btn = wx.Button(self.pl, label='保存聊天记录', size=(200, 40), pos=(220, 10))
        # 创建聊天内容的文本框
        self.text = wx.TextCtrl(self.pl, size=(420, 400), pos=(10, 60), style=wx.TE_READONLY | wx.TE_MULTILINE)

        # 按钮事件绑定
        self.Bind(wx.EVT_BUTTON, self.start, self.start_btn)
        self.Bind(wx.EVT_BUTTON, self.save, self.save_btn)

    # 点击按钮触发的相应事件
    # 启动服务器
    def start(self, event):
        if not self.isOn:
            self.isOn = True
            print('start')
            self.send('======【服务器启动成功】======')
            # 创建线程
            main_thread = threading.Thread(target=self.main_thread_fun)
            # 设置守护线程
            main_thread.daemon = True
            # 启动线程
            main_thread.start()

    def main_thread_fun(self):
        while self.isOn:
            # 获取客户端信息
            client_socket, client_addr = self.server_socket.accept()
            print(client_addr)
            # 设置编码
            client_name = client_socket.recv(1024).decode('utf8')
            print(client_name)

            # 创建客户端线程
            client_thread = ClientThread(client_socket, client_name, self)
            # 保存客户端线程到线程字典
            self.client_thread_dict[client_name] = client_thread
            # 将线程提交到线程池
            self.pool.submit(client_thread.run)

            self.send('【服务器消息】%s加入了聊天室' % client_name)

    # 给当前所有服务端和客户端群发的消息
    def send(self, text):
        # 发送给服务端
        self.text.AppendText(text + '\n')
        # 发送给客户端
        for client in self.client_thread_dict.values():
            if client.isOn:
                client.client_socket.send(text.encode('utf8'))

    # 保存聊天记录
    def save(self, event):

        record = self.text.GetValue()
        with open('record.log', 'a+', encoding='utf8') as f:
            f.write(record)
        print('save')

class ClientThread(threading.Thread):
    def __init__(self, socket, name, server):
        threading.Thread.__init__(self)
        self.client_socket = socket
        self.client_name = name
        self.server = server
        self.isOn = True

    def run(self):
        while self.isOn:
            text = self.client_socket.recv(1024).decode('utf8')
            if text == '断开连接':
                self.isOn = False
                #发送给当前所有线程的客户端和服务端
                self.server.send('【服务器消息】%s离开了聊天室' % self.client_name)
            else:
                self.server.send('【%s】：%s' % (self.client_name, text))
        # 关闭客户端
        self.client_socket.close()


# 程序人口
if __name__ == '__main__':
    # 创建应用对象
    app = wx.App()
    # 创建客户端窗口
    server = Server()
    # 显示客户端窗口
    server.Show()
    # 循环显示
    app.MainLoop()
